#include "SALT_Graphics.h"

#include "SDL/SDL.h"
#include "SDL/SDL_gfxPrimitives.h"

namespace SALT{
	namespace Graphics{
		SDLGraphicsManager::SDLGraphicsManager(){
			SDLGraphicsManager(800,600,32,SDL_HWSURFACE|SDL_DOUBLEBUF);
		}
		SDLGraphicsManager::SDLGraphicsManager(unsigned int screenWidth, unsigned int screenHeight, unsigned int bpp,unsigned int flags):_AbstractGraphicsManager<SDL_Surface*>(){
			if(!(SDL_WasInit(SDL_INIT_EVERYTHING)&SDL_INIT_VIDEO)){
				SDL_Init(SDL_INIT_EVERYTHING);
				this->_initedSDL=true;
			}else
				this->_initedSDL=false;
			this->_screen=SDL_SetVideoMode(screenWidth,screenHeight,bpp,flags);
			//this->_clips.push(NULL);
			this->_eventManager=new SALT::Events::SDLEventManager();
		}
		SDLGraphicsManager::~SDLGraphicsManager(){
			if(this->_initedSDL)
				SDL_Quit();
		}
		Point SDLGraphicsManager::_addClip(Point* p){
			Point ret(p->x,p->y);
			if(this->_clips.size()>0){
				Point* cp=this->_clips.top();
				ret.x+=cp->x;
				ret.y+=cp->y;
			}
			return ret;
		}
		void SDLGraphicsManager::blit(SDL_Surface *surf, Point &pos, Point *size){
			Point dp=_addClip(&pos);
			SDL_Rect br={dp.x,dp.y,0,0};
			SDL_Rect sr;
			if(size!=NULL){
				sr.x=sr.y=0;
				sr.w=size->x;
				sr.h=size->y;
			}
			else{
				sr.x=sr.y=0;
				sr.w=surf->w;
				sr.h=surf->h;
			}
			int ret=SDL_BlitSurface(surf,&sr,this->_screen,&br);
		}
		void SDLGraphicsManager::drawEllipse(Point &center, int vAxisLength, int hAxisLength,unsigned short r,unsigned short b,unsigned short g,unsigned short a){
			Point cp=_addClip(&center);
			ellipseRGBA(this->_screen,cp[0]-hAxisLength/2,cp[1]-vAxisLength/2,hAxisLength,vAxisLength,r,g,b,a);
		}
		void SDLGraphicsManager::drawLine(Point &p1, Point &p2, unsigned short r, unsigned short b, unsigned short g, unsigned short a){
			Point cp1=_addClip(&p1);
			Point cp2=_addClip(&p2);
			lineRGBA(this->_screen,cp1[0],cp1[1],cp2[0],cp2[1],r,g,b,a);
		}
		void SDLGraphicsManager::drawRect(Point &tlCorner, Point &brCorner, unsigned short r, unsigned short b, unsigned short g, unsigned short a){
			Point tl=_addClip(&tlCorner);
			Point br=_addClip(&brCorner);
			rectangleRGBA(this->_screen,tl[0],tl[1],br[0],br[1],r,g,b,a);
		}
		void SDLGraphicsManager::handleEvent(void *data){
			if(this->_eventManager!=NULL)
				this->_eventManager->handleEvent(data);
		}
		void SDLGraphicsManager::pushClip(Point* clip){
			Point* p=new Point(clip->x,clip->y);
			//each clip point is in reference to the one above it, if there is one
			if(this->_clips.size()>0){
				Point* cp=this->_clips.top();
				p->x+=cp->x;
				p->y+=cp->y;
			}
			this->_clips.push(p);
		}
		Point* SDLGraphicsManager::popClip(){
			Point* p=NULL;
			//TODO: since points are in ref, make sure to subtract the top one
			if(this->_clips.size()>0){
				this->_clips.top();
				this->_clips.pop();
			}
			return p;
		}
		void SDLGraphicsManager::flip(){
			SDL_Flip(this->_screen);
		}
		void SDLGraphicsManager::clear(){
			static Uint32 clearColor=SDL_MapRGB(this->_screen->format,255,0,255);
			SDL_FillRect(this->_screen,NULL,clearColor);
		}
	};
};